package com.ygqh.baby.controller.admin;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.ygqh.baby.ao.AppType;
import com.ygqh.baby.ao.CodeType;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.ao.PayType;
import com.ygqh.baby.po.YgOrder;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.alipay.util.AlipayNotify;
import com.ygqh.baby.service.alipay.util.AlipaySubmit;
import com.ygqh.baby.service.impl.DocumentConstant;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;

/**
 * 微信相关接口
 *
 * @author guohao
 */
@Controller
@RequestMapping("/agent/alipay")
public class AlipayController {
    protected final Logger logger = Logger.getLogger(this.getClass());
    @Autowired
    private YgOrderService orderService;
    @Autowired
    private YgOrderPaymentService orderPaymentService;
    @Autowired
    private YgFrameCodeService ygFrameCodeService;
    @Autowired
    private YgAccountDetailService ygAccountDetailService;
    @Autowired
    private AlipayNotify AlipayNotify;
    @Autowired
    private AlipaySubmit AlipaySubmit;
    @Value("${alipay.partner}")
    private String partner;
    @Value("${alipay.seller_id}")
    private String sellerId;
    @Value("${alipay.key}")
    private String key;
    @Value("${alipay.notify_url}")
    private String notify_url;
    @Value("${alipay.return_url}")
    private String return_url;
    @Value("${alipay.recharge.notify_url}")
    private String recharge_notify_url;
    @Value("${alipay.recharge.return_url}")
    private String recharge_return_url;
    @Value("${alipay.payment_type}")
    private String payment_type;
    @Value("${alipay.sign_type}")
    private String sign_type;
    @Value("${alipay.api}")
    private String api;
    @Value("${alipay.charset}")
    private String charset;
    @Value("${alipay.gatewayUrl}")
    private String gatewayUrl;
    @Value("${alipay.refund.service}")
    private String refundService;
    @Autowired
    private DocumentConstant documentConstant;
    @Autowired
    private YgOrderLogService ygOrderLogService;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;

    @RequestMapping(value = "toAlipayIndex", method = RequestMethod.GET)
    public String toAlipayIndex(Model model) {
        List<YgOrder> list = orderService.find();
        Long orderId = 1l;
        for (YgOrder order : list) {
            orderId = order.getOrderId();
            break;
        }
        model.addAttribute("orderId", orderId);
        return "alipayindex";
    }

    @RequestMapping(value = "toAlipayApi", method = RequestMethod.GET)
    @ResponseBody
    public Message toAlipayApi(String state, HttpServletRequest request, HttpServletResponse out, String callback) throws UnsupportedEncodingException {
        out.setHeader("Content-type", "text/html;charset=UTF-8");
        out.setCharacterEncoding("UTF-8");

        // ////////////////////////////////////////////////////////////////////////////////

        // 生成支付流水
        String[] str = state.split("-");
        Long paymentCode = ygFrameCodeService.getFrameCode(CodeType.OrderPM, new Date());
        orderPaymentService.addPaymentRecord(str[0], new BigDecimal(str[1]), paymentCode.toString(), PayType.Alipay, AppType.WeChat);

        // 把请求参数打包成数组
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("service", api);
        sParaTemp.put("partner", partner);
        sParaTemp.put("seller_id", sellerId);
        sParaTemp.put("_input_charset", charset);
        sParaTemp.put("payment_type", payment_type);
        sParaTemp.put("notify_url", notify_url);
        sParaTemp.put("return_url", return_url + "?state=" + state);
        sParaTemp.put("out_trade_no", paymentCode.toString());
        sParaTemp.put("subject", "壹果订单");
        sParaTemp.put("total_fee", str[1]);
        sParaTemp.put("show_url", "");
        // sParaTemp.put("app_pay","Y");//启用此参数可唤起钱包APP支付。
        sParaTemp.put("body", "壹果订单");
        // 其他业务参数根据在线开发文档，添加参数.文档地址:https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.2Z6TSk&treeId=60&articleId=103693&docType=1
        // 如sParaTemp.put("参数名","参数值");
        // 建立请求
        String sHtmlText = AlipaySubmit.buildRequest(sParaTemp, "post", "确认");
        return Message.success(documentConstant.MESSAGE_SUCCESS, sHtmlText);

    }

    @RequestMapping(value = "returnUrl")
    @ResponseBody
    public JSONPObject returnUrl(HttpServletRequest request, HttpServletResponse out, String callback) throws IOException {
        out.setHeader("Content-type", "text/html;charset=UTF-8");
        // 这句话的意思，是告诉servlet用UTF-8转码，而不是用默认的ISO8859
        out.setCharacterEncoding("UTF-8");
        // String paramss = new
        // String(request.getParameter("params").getBytes("ISO-8859-1"),
        // "UTF-8");
        // 获取支付宝GET过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        logger.info(requestParams.toString());
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            /*
             * valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
             */
            params.put(name, valueStr);
        }

        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        String total_fee = new String(request.getParameter("total_fee").getBytes("ISO-8859-1"), "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        // 计算得出通知验证结果
        boolean verify_result = AlipayNotify.verify(params);
        if (verify_result) {// 验证成功
            // ////////////////////////////////////////////////////////////////////////////////////////
            // 请在这里加上商户的业务逻辑程序代码

            // ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
            if (trade_status.equals("TRADE_SUCCESS")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序
                orderService.doBussness4PaySuccess(out_trade_no, trade_no, new BigDecimal(total_fee), AppType.WeChat, PayType.Alipay);
            }

            // 该页面可做页面美工编辑
            // out.getWriter().println(headerString + "<br />");
            // ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

            // ////////////////////////////////////////////////////////////////////////////////////////
            return new JSONPObject(callback, Message.success(documentConstant.MESSAGE_SUCCESS, "验证成功"));
        } else {
            // 该页面可做页面美工编辑
            // out.getWriter().println(headerString);
            return new JSONPObject(callback, Message.error(documentConstant.MESSAGE_ERROR, "验证失败"));
        }

    }

    @RequestMapping(value = "notifyUrl")
    public void notifyUrl(HttpServletRequest request, HttpServletResponse out) throws IOException {
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            /*
             * valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
             */
            params.put(name, valueStr);
        }
        logger.info(params.toString());

        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        // 交易金额
        String total_fee = new String(request.getParameter("total_fee").getBytes("ISO-8859-1"), "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        String result = "success";

        if (AlipayNotify.verify(params)) {// 验证成功
            // ////////////////////////////////////////////////////////////////////////////////////////
            try {
                if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) {
                    // 拆单 回写支付流水,同步订单
                    orderService.doBussness4PaySuccess(out_trade_no, trade_no, new BigDecimal(total_fee), AppType.WeChat, PayType.Alipay);
                }
            } catch (Exception e) {
                result = "false";
                e.printStackTrace();
            }
            // ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

            logger.debug("支付宝异步回调验证成功===============out_trade_no :" + out_trade_no + "===========");
            out.getWriter().print(result); // 请不要修改或删除
            System.out.println("notifyUrl==========" + result);

            // return result;
        } else {// 验证失败
            logger.error("支付宝异步回调验证失败===============out_trade_no :" + out_trade_no + "===========");
            System.out.println("notifyUrl==========" + result);
            out.getWriter().print(result);
            // return result;
        }

    }

    @RequestMapping(value = "rechargeNotifyUrl")
    public void rechargeNotifyUrl(HttpServletRequest request, HttpServletResponse out) throws IOException {
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            /*
             * valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
             */
            params.put(name, valueStr);
        }

        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        // 交易金额
        String total_fee = new String(request.getParameter("total_fee").getBytes("ISO-8859-1"), "UTF-8");

        String userId = new String(request.getParameter("body").getBytes("ISO-8859-1"), "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        String result = "success";

        if (AlipayNotify.verify(params)) {// 验证成功
            // ////////////////////////////////////////////////////////////////////////////////////////
            try {
                if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) {
                    // 校验成功，回写金额
                    ygAccountDetailService.doBussnessForPaySuccess(Long.parseLong(out_trade_no), Long.parseLong(userId), new BigDecimal(total_fee),
                            PayType.Alipay, "rechargeNotifyUrl");
                }
            } catch (Exception e) {
                result = "false";
                e.printStackTrace();
            }
            // ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

            logger.debug("支付宝异步回调验证成功===============out_trade_no :" + out_trade_no + "===========");
            out.getWriter().print(result); // 请不要修改或删除
            System.out.println("notifyUrl==========" + result);

            // return result;
        } else {// 验证失败
            logger.debug("支付宝异步回调验证失败===============out_trade_no :" + out_trade_no + "===========");
            System.out.println("notifyUrl==========" + result);
            out.getWriter().print(result);
            // return result;
        }

    }

    private Map<String, String> getAlipayNotifyParam(HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>();
        Map<?, ?> requestParams = request.getParameterMap();
        for (Iterator<?> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            /*
             * valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
             */
            params.put(name, valueStr);
        }
        return params;
    }

}
